﻿using System;

using OpenTK;
using OpenTK.Graphics;
using OpenTK.Graphics.OpenGL;

namespace Interface.Visualization
{
    // Credit to THOMASFN (http://pastebin.com/1izZZb54)
    public class Shader
    {
        private int iVertexShader;
        private int iFragShader;

        private int iProgram;

        private bool bOk;

        public Shader(string vertex, string frag)
        {
            iProgram = GL.CreateProgram();
            bOk = true;
            int result;

            iVertexShader = GL.CreateShader(ShaderType.VertexShader);
            GL.ShaderSource(iVertexShader, vertex);
            GL.CompileShader(iVertexShader);
            GL.GetShader(iVertexShader, ShaderParameter.CompileStatus, out result);
            if (result == 0)
            {
                bOk = false;
                Console.WriteLine("Failed to compile vertex shader!");
                Console.WriteLine(GL.GetShaderInfoLog(iVertexShader));
            }

            iFragShader = GL.CreateShader(ShaderType.FragmentShader);
            GL.ShaderSource(iFragShader, frag);
            GL.CompileShader(iFragShader);
            GL.GetShader(iFragShader, ShaderParameter.CompileStatus, out result);
            if (result == 0)
            {
                bOk = false;
                Console.WriteLine("Failed to compile fragment shader!");
                Console.WriteLine(GL.GetShaderInfoLog(iFragShader));
            }

            GL.AttachShader(iProgram, iVertexShader);
            GL.AttachShader(iProgram, iFragShader);

            GL.LinkProgram(iProgram);

            GL.GetProgram(iProgram, ProgramParameter.LinkStatus, out result);
            if (result == 0)
            {
                bOk = false;
                Console.WriteLine("Failed to link shader program!");
                Console.WriteLine(GL.GetProgramInfoLog(iProgram));
            }
        }

        public void SetUniform(string name, float value)
        {
            int loc = GL.GetUniformLocation(iProgram, name);
            GL.Uniform1(loc, value);
        }
        public void SetUniform(string name, Vector3 value)
        {
            int loc = GL.GetUniformLocation(iProgram, name);
            GL.Uniform3(loc, ref value);
        }
        public void SetUniform(string name, Vector4 value)
        {
            int loc = GL.GetUniformLocation(iProgram, name);
            GL.Uniform4(loc, ref value);
        }

        public void Activate()
        {
            if (bOk) { GL.UseProgram(iProgram); }
        }

        public void Deactivate()
        {
            GL.UseProgram(0);
        }
    }
}
